/*
 * Copyright (C) 2013 TinhVan Outsourcing.
 * 
 * FacebookUtils.java
 * 
 * Created on: 26-11-2013 - 14:34:24 Author: VanNT
 */

package com.media.themovieworld.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;

import com.facebook.FacebookRequestError;
import com.facebook.FacebookRequestError.Category;
import com.facebook.HttpMethod;
import com.facebook.Request;
import com.facebook.Request.GraphUserCallback;
import com.facebook.RequestAsyncTask;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.SessionLoginBehavior;
import com.facebook.SessionState;
import com.facebook.internal.Utility;
import com.facebook.model.GraphUser;

/**
 * FacebookUtils helper class new version
 * 
 * @author TuyenND Jan 16, 2014 <br/>
 *         <b>Note*: Do remember to implement onActivityResult to handle session callback</b>
 * 
 * <pre>
 * 
 * add to Manifest file
 * {@code 
 * <uses-permission android:name="android.permission.INTERNET"/>
 * <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 * <activity android:name="com.facebook.LoginActivity"
 *                 android:theme="@android:style/Theme.Translucent.NoTitleBar"
 *                 android:label="@string/app_name" />
 * <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/app_id"/>
 *  }  
 *  <br/>
 *  add to activity
 * @Override
 * public void onActivityResult(int requestCode, int resultCode, Intent data) 
 * {
 * 	 super.onActivityResult(requestCode, resultCode, data);
 * 	 FacebookUtils.onActivityResult(this, requestCode, resultCode, data);
 * }
 * 
 * </pre>
 */
public final class FacebookUtils {
    private static final String PUBLISH_ACTIONS = "publish_actions";
    private static final String PUBLISH_STREAM = "publish_stream";
    private static final String EMAIL = "email";
    private static final String USER_LOCATION = "user_location";
    private static final String USER_BIRTHDAY = "user_birthday";
    private static final String PUBLIC_PROFILE = "public_profile";

    private static final String USER_ABOUT = "user_about_me";
    // private static final String BASIC_PER = "basic_info";
    private static final String READ_STREAM = "read_stream";
    private static final String READ_I = "read_insights";

    /**
     * only Logout Facebook session in My app
     * 
     * @param context
     */
    public static void logoutFaceBook(final Context context) {
        final Session session = Session.getActiveSession();
        if (session != null) {
            session.closeAndClearTokenInformation();
            Utility.clearFacebookCookies(context);
        }
    }

    /**
     * Called in onCreate Activity to do get Hashkey Facebook app
     * 
     * @param pActivity
     */
    public static void getHashKeyFaceBook(final Activity pActivity) {
        // Add code to print out the key hash
        try {
            final PackageInfo info =
                    pActivity.getPackageManager().getPackageInfo(pActivity.getPackageName(),
                            PackageManager.GET_SIGNATURES);
            for (final Signature signature : info.signatures) {
                final MessageDigest md = MessageDigest.getInstance("SHA");
                md.update(signature.toByteArray());
                Log.e("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
            }
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Called in onActivityResult of Activity implement
     * 
     * @param pActivity
     * @param requestCode
     * @param resultCode
     * @param data
     */
    public static void onActivityResult(final Activity pActivity, final int requestCode,
            final int resultCode, final Intent data) {
        if (Session.getActiveSession() != null) {
            Session.getActiveSession().onActivityResult(pActivity, requestCode, resultCode, data);
        }
    }

    /**
     * Function method login to Facebook, onActivityResult session handler need to be implement for
     * function to work properly
     * 
     * <pre>
	 * &#064;Override
	 * public void onActivityResult(int requestCode, int resultCode, Intent data) {
	 * 	super.onActivityResult(requestCode, resultCode, data);
	 * 	FacebookUtils.onActivityResult(this, requestCode, resultCode, data);
	 * }
	 * </pre>
     * 
     * Login to facebook and get user infor
     * 
     * @param pActivity
     * @param pdialog
     * @param pFacebookListener
     */
    public static void loginToFacebook(final Activity pActivity, final ProgressDialog pdialog,
            final FacebookListener pFacebookListener) {
        pdialog.setCancelable(false);
        pdialog.setMessage("Please wait ...");
        pdialog.show();
        final Session session = Session.getActiveSession();
        if (session == null || !session.isOpened()) {
            Session.openActiveSession(pActivity, true, new Session.StatusCallback() {
                @Override
                public void call(Session session, SessionState state, Exception exception) {
                    if (exception == null && session.isOpened()) {
                        loginToFacebook(pActivity, pdialog, pFacebookListener);
                    } else if (exception != null) {
                        exception.printStackTrace();
                        pdialog.dismiss();
                        // TODO Login Fail
                        if (pFacebookListener != null) {
                            pFacebookListener.onFail();
                        }
                    } else {
                        pdialog.dismiss();
                    }
                }
            });
        } else {
            final List<String> arrPermistion = Arrays.asList(EMAIL, USER_LOCATION, USER_BIRTHDAY, USER_ABOUT, PUBLIC_PROFILE);
            if (!session.getPermissions().contains(EMAIL)
                    || !session.getPermissions().contains(USER_LOCATION)
                    || !session.getPermissions().contains(USER_BIRTHDAY)
            /* || !session.getPermissions().contains(USER_ABOUT) */) {
                final Session.NewPermissionsRequest request =
                        new Session.NewPermissionsRequest(pActivity, arrPermistion);
                session.requestNewReadPermissions(request);
                pdialog.dismiss();
            } else {
                final GraphUserCallback callBack = new GraphUserCallback() {
                    @Override
                    public void onCompleted(GraphUser user, Response response) {
                        final FacebookRequestError error = response.getError();
                        if (error == null) {
                            if (pFacebookListener != null) {
                                pFacebookListener.onSuccess(response);
                            }
                        } else {
                            final Category category = error.getCategory();
                            if (category == Category.AUTHENTICATION_REOPEN_SESSION
                                    || category == Category.AUTHENTICATION_RETRY) {
                                final Session session = Session.getActiveSession();
                                session.closeAndClearTokenInformation();
                            }
                            Log.e("LoginToFacebook", error.getErrorMessage());
                            // TODO Login Fail
                            if (pFacebookListener != null) {
                                pFacebookListener.onFail();
                            }
                        }
                        pdialog.dismiss();
                    }
                };
                final Request request = Request.newMeRequest(session, callBack);
                final RequestAsyncTask task = new RequestAsyncTask(request);
                task.execute();
            }
        }
    }

    /**
     * Function method to post bitmap image to Facebook, onActivityResult session handler need to be
     * implement for function to work properly
     * 
     * <pre>
	 * &#064;Override
	 * public void onActivityResult(int requestCode, int resultCode, Intent data) {
	 * 	super.onActivityResult(requestCode, resultCode, data);
	 * 	FacebookUtils.onActivityResult(this, requestCode, resultCode, data);
	 * }
	 * </pre>
     * 
     * - when you post bitmap U must add permissions
     * 
     * @param pActivity context of activity
     * @param pdialog progress dialog to show progress on activity
     * @param bitmap bitmap to be posted to Facebook
     * @param pMessage - mesg share to wall
     */
    public static void postBitmap(final Activity pActivity, final ProgressDialog pdialog,
            final Bitmap bitmap, final String pMessage, final FacebookListener pFacebookListener) {
        pdialog.setCancelable(false);
        pdialog.setMessage("Please wait ...");
        pdialog.show();
        final Session session = Session.getActiveSession();
        if (session == null || !session.isOpened()) {
            Session.openActiveSession(pActivity, true, new Session.StatusCallback() {
                @Override
                public void call(Session session, SessionState state, Exception exception) {
                    if (exception == null && session.isOpened()) {
                        postBitmap(pActivity, pdialog, bitmap, pMessage, pFacebookListener);
                    } else if (exception != null) {
                        exception.printStackTrace();
                        pdialog.dismiss();
                        Toast.makeText(pActivity, "Post fail", Toast.LENGTH_SHORT).show();
                        if (pFacebookListener != null) {
                            pFacebookListener.onFail();
                        }
                    } else {
                        pdialog.dismiss();
                    }
                }
            });
        } else {
            if (!session.getPermissions().contains(PUBLISH_ACTIONS)) {
                final Session.NewPermissionsRequest request =
                        new Session.NewPermissionsRequest(pActivity, Arrays.asList(PUBLISH_ACTIONS,
                                PUBLISH_STREAM));
                session.requestNewPublishPermissions(request);
                pdialog.dismiss();
            } else {
                final Request.Callback callBack = new Request.Callback() {
                    @Override
                    public void onCompleted(Response response) {
                        pdialog.dismiss();
                        final FacebookRequestError error = response.getError();
                        if (error == null) {
                            Toast.makeText(pActivity, "Post success", Toast.LENGTH_SHORT).show();
                            if (pFacebookListener != null) {
                                pFacebookListener.onSuccess(response);
                            }
                        } else {
                            final Category category = error.getCategory();
                            if (category == Category.AUTHENTICATION_REOPEN_SESSION
                                    || category == Category.AUTHENTICATION_RETRY) {
                                final Session session = Session.getActiveSession();
                                session.closeAndClearTokenInformation();
                            }
                            Toast.makeText(pActivity, "Post fail :" + error.toString(), Toast.LENGTH_SHORT)
                                    .show();
                            if (pFacebookListener != null) {
                                pFacebookListener.onFail();
                            }
                        }
                    }
                };
                final Request request =
                        Request.newUploadPhotoRequest(Session.getActiveSession(), bitmap, callBack);
                final Bundle params = request.getParameters();
                params.putString("message", pMessage);
                // with text
                request.setParameters(params);
                final RequestAsyncTask task = new RequestAsyncTask(request);
                task.execute();
            }
        }
    }

    /**
     * Function method to post video to Facebook, onActivityResult session handler need to be
     * implement for function to work properly
     * 
     * <pre>
	 * &#064;Override
	 * public void onActivityResult(int requestCode, int resultCode, Intent data) {
	 * 	super.onActivityResult(requestCode, resultCode, data);
	 * 	FacebookUtils.onActivityResult(this, requestCode, resultCode, data);
	 * }
	 * </pre>
     * 
     * @param pActivity
     * @param pDialog
     * @param pFacebookListener
     */
    public static void postVideo(final Activity pActivity, final ProgressDialog pDialog, final String pTitle,
            final String pMessage, final String pVideoFilePath, final FacebookListener pFacebookListener) {
        final Session session = Session.getActiveSession();
        pDialog.setCancelable(false);
        pDialog.setMessage("loading ...");
        pDialog.show();
        // If the session is open
        if (session != null && session.isOpened()) {
            // Get the list of permissions associated with the session
            final List<String> permissions = session.getPermissions();
            // if the session does not have video_upload permission
            if (!permissions.contains("video_upload")) {
                // Get the permission from user to upload the video to facebook
                Session.NewPermissionsRequest newPermissionsRequest =
                        new Session.NewPermissionsRequest(pActivity, Arrays.asList("video_upload"));
                session.requestNewReadPermissions(newPermissionsRequest);
            }
            // Create a new file for the video
            final File file = new File(pVideoFilePath);
            try {
                // create a new request to upload video to the facebook
                final Request videoRequest =
                        Request.newUploadVideoRequest(session, file, new Request.Callback() {
                            @Override
                            public void onCompleted(Response response) {
                                if (response.getError() == null) {
                                    Toast.makeText(pActivity, "video shared successfully", Toast.LENGTH_SHORT)
                                            .show();
                                    if (pFacebookListener != null) {
                                        pFacebookListener.onSuccess(response);
                                    }
                                } else {
                                    Toast.makeText(pActivity, response.getError().getErrorMessage(),
                                            Toast.LENGTH_SHORT).show();
                                    if (pFacebookListener != null) {
                                        pFacebookListener.onFail();
                                    }
                                }
                                pDialog.dismiss();
                            }
                        });
                final Bundle params = videoRequest.getParameters();
                params.putString("message", pMessage);
                params.putString("title", pTitle);
                videoRequest.setParameters(params);
                // Execute the request in a separate thread
                videoRequest.executeAsync();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } else { // Session is not open
            Session.openActiveSession(pActivity, true, new Session.StatusCallback() {
                @Override
                public void call(Session session, SessionState state, Exception exception) {
                    if (exception == null && session.isOpened()) {
                        postVideo(pActivity, pDialog, pTitle, pMessage, pVideoFilePath, pFacebookListener);
                    } else if (exception != null) {
                        exception.printStackTrace();
                        pDialog.dismiss();
                        Toast.makeText(pActivity, "Post fail", Toast.LENGTH_SHORT).show();
                        if (pFacebookListener != null) {
                            pFacebookListener.onFail();
                        }
                    } else {
                        pDialog.dismiss();
                    }
                }
            });
            // Toast.makeText(act, "Please login to facebook first",
            // Toast.LENGTH_SHORT).show();
        }

    }

    /**
     * Function method to post video to Facebook, onActivityResult session handler need to be
     * implement for function to work properly
     * 
     * <pre>
	 * &#064;Override
	 * public void onActivityResult(int requestCode, int resultCode, Intent data) {
	 * 	super.onActivityResult(requestCode, resultCode, data);
	 * 	FacebookUtils.onActivityResult(this, requestCode, resultCode, data);
	 * }
	 * </pre>
     * 
     * @param pActivity
     * @param pdialog
     * @param pTitle
     * @param pPictureURL
     * @param pMessage
     * @param pTextCaption
     * @param pTextDescription
     * @param pFacebookListener
     */
    public static void postFeed_toWall(final Activity pActivity, final ProgressDialog pdialog,
            final String pTitle, final String pPictureURL, final String pMessage, final String pTextCaption,
            final String pTextDescription, final FacebookListener pFacebookListener) {
        pdialog.setCancelable(false);
        pdialog.setMessage("Please wait ...");
        pdialog.show();
        final Session session = Session.getActiveSession();
        if (session == null || !session.isOpened()) {
            Session.openActiveSession(pActivity, true, new Session.StatusCallback() {
                @Override
                public void call(Session session, SessionState state, Exception exception) {
                    if (exception == null && session.isOpened()) {
                        postFeed_toWall(pActivity, pdialog, pTitle, pPictureURL, pMessage, pTextCaption,
                                pTextDescription, pFacebookListener);
                    } else if (exception != null) {
                        exception.printStackTrace();
                        pdialog.dismiss();
                        Toast.makeText(pActivity, "Post fail", Toast.LENGTH_SHORT).show();
                        if (pFacebookListener != null) {
                            pFacebookListener.onFail();
                        }
                    } else {
                        pdialog.dismiss();
                    }
                }
            });
        } else {
            if (!session.getPermissions().contains(PUBLISH_ACTIONS)) {
                final Session.NewPermissionsRequest request =
                        new Session.NewPermissionsRequest(pActivity, Arrays.asList(PUBLISH_ACTIONS));
                session.requestNewPublishPermissions(request);
                pdialog.dismiss();
            } else {
                final Request.Callback callBack = new Request.Callback() {
                    @Override
                    public void onCompleted(Response response) {
                        pdialog.dismiss();
                        final FacebookRequestError error = response.getError();
                        if (error == null) {
                            Toast.makeText(pActivity, "Post success", Toast.LENGTH_SHORT).show();
                            if (pFacebookListener != null) {
                                pFacebookListener.onSuccess(response);
                            }
                        } else {
                            final Category category = error.getCategory();
                            if (category == Category.AUTHENTICATION_REOPEN_SESSION
                                    || category == Category.AUTHENTICATION_RETRY) {
                                final Session session = Session.getActiveSession();
                                session.closeAndClearTokenInformation();
                            }
                            Toast.makeText(pActivity, "Post fail :" + error.toString(), Toast.LENGTH_SHORT)
                                    .show();
                            if (pFacebookListener != null) {
                                pFacebookListener.onFail();
                            }
                        }
                    }
                };
                final Bundle postParams = new Bundle();
                postParams.putString("picture", pPictureURL);
                postParams.putString("message", pMessage);
                postParams.putString("name", pTitle);
                postParams.putString("caption", pTextCaption);
                postParams.putString("description", pTextDescription);
                final Request request =
                        new Request(Session.getActiveSession(), "me/feed", postParams, HttpMethod.POST,
                                callBack);
                final RequestAsyncTask task = new RequestAsyncTask(request);
                task.execute();
            }
        }
    }

    /**
     * Function method to post video to Facebook, onActivityResult session handler need to be
     * implement for function to work properly
     * 
     * <pre>
	 * &#064;Override
	 * public void onActivityResult(int requestCode, int resultCode, Intent data) {
	 * 	super.onActivityResult(requestCode, resultCode, data);
	 * 	FacebookUtils.onActivityResult(this, requestCode, resultCode, data);
	 * }
	 * </pre>
     * 
     * @param pActivity
     * @param pdialog
     * @param pMessage
     * @param pFacebookListener
     */
    public void postStatus_toWall(final Activity pActivity, final ProgressDialog pdialog,
            final String pMessage, final FacebookListener pFacebookListener) {
        pdialog.setCancelable(false);
        pdialog.setMessage("Please wait ...");
        pdialog.show();
        final Session session = Session.getActiveSession();
        if (session == null || !session.isOpened()) {
            Session.openActiveSession(pActivity, true, new Session.StatusCallback() {
                @Override
                public void call(Session session, SessionState state, Exception exception) {
                    if (exception == null && session.isOpened()) {
                        postStatus_toWall(pActivity, pdialog, pMessage, pFacebookListener);
                    } else if (exception != null) {
                        exception.printStackTrace();
                        pdialog.dismiss();
                        Toast.makeText(pActivity, "Post fail", Toast.LENGTH_SHORT).show();
                        if (pFacebookListener != null) {
                            pFacebookListener.onFail();
                        }
                    } else {
                        pdialog.dismiss();
                    }
                }
            });
        } else {
            if (!session.getPermissions().contains(PUBLISH_ACTIONS)) {
                final Session.NewPermissionsRequest request =
                        new Session.NewPermissionsRequest(pActivity, Arrays.asList(PUBLISH_ACTIONS));
                session.requestNewPublishPermissions(request);
                pdialog.dismiss();
            } else {
                final Request.Callback callBack = new Request.Callback() {
                    @Override
                    public void onCompleted(Response response) {
                        pdialog.dismiss();
                        final FacebookRequestError error = response.getError();
                        if (error == null) {
                            Toast.makeText(pActivity, "Post success", Toast.LENGTH_SHORT).show();
                            if (pFacebookListener != null) {
                                pFacebookListener.onSuccess(response);
                            }
                        } else {
                            final Category category = error.getCategory();
                            if (category == Category.AUTHENTICATION_REOPEN_SESSION
                                    || category == Category.AUTHENTICATION_RETRY) {
                                final Session session = Session.getActiveSession();
                                session.closeAndClearTokenInformation();
                            }
                            Toast.makeText(pActivity, "Post fail :" + error.toString(), Toast.LENGTH_SHORT)
                                    .show();
                            if (pFacebookListener != null) {
                                pFacebookListener.onFail();
                            }
                        }
                    }
                };
                final Request request = Request.newStatusUpdateRequest(session, pMessage, callBack);
                final RequestAsyncTask task = new RequestAsyncTask(request);
                task.execute();
            }
        }
    }

    // called in OnCreat Activity
    public static Session openActiveSession(final Activity activity, final Bundle savedInstanceState) {

        Session session = Session.getActiveSession();
        if (session == null) {
            if (savedInstanceState != null) {
                session = Session.restoreSession(activity, null, null, savedInstanceState);
            }
            if (session == null) {
                session = new Session(activity);
            }
            Session.setActiveSession(session);
            return session;
        }
        return null;
    }

    public static void onSaveInstanceState(Bundle outState) {
        Session session = Session.getActiveSession();
        Session.saveSession(session, outState);
    }

    // delegate----
    /**
     * listener facebook task execute
     * 
     * @author TuyenND Jan 16, 2014
     */
    public interface FacebookListener {
        /**
         * Called when task execute success
         * 
         * @param pResponse
         */
        void onSuccess(Response pResponse);

        /**
         * Called when task execute fail
         * 
         * @param pResponse
         */
        void onFail();
    }

    /**
     * Note : package com.facebook.widget.WebDialog; line 201 : ProgressDialog fix dissmiss
     */
}
